package com.jeequan.jeepay.pay.channel.pmipay;

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.pay.channel.AbstractChannelNoticeService;
import com.jeequan.jeepay.pay.model.MchAppConfigContext;
import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.service.impl.PayOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;

/**
 * Paymob放款订单交易状态通知回调
 */
@Slf4j
@Service
public class PmipayChannelNoticeService extends AbstractChannelNoticeService {

    @Autowired
    private PayOrderService payOrderService;

    @Override
    public String getIfCode() {
        return CS.IF_CODE.PMIPAY;
    }

    @Override
    public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {

        try {
            // 解析通知参数
            String bodyText = getBody(request);
            log.info("解析通知参数：{}", bodyText);

            JSONObject body = JSONObject.parseObject(bodyText);
            String channelOrderNo = body.getString("transaction_id");

            // 根据渠道订单号查询订单
            PayOrder order = payOrderService.queryByChannelOrderNo(channelOrderNo);
            if (order == null) {
                log.error("交易订单不存在: {}", channelOrderNo);
                return null;
            }
            String payOrderId = order.getPayOrderId();
            return MutablePair.of(payOrderId, body);

        } catch (Exception e) {
            log.error("参数解析异常", e);
            throw ResponseException.buildText("参数解析异常");
        }
    }

    @Override
    public ChannelRetMsg doNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) {
        ChannelRetMsg channelRetMsg = new ChannelRetMsg();
        JSONObject body = (JSONObject) params;
        String statusCode = body.getString("status_code");
        String statusMsg = body.getString("disbursement_status");
        channelRetMsg.setChannelErrCode(statusCode);
        channelRetMsg.setChannelOriginResponse(body.toJSONString());
        channelRetMsg.setChannelOrderId(payOrder.getChannelOrderNo());
        channelRetMsg.setResponseEntity(ResponseEntity.ok().body("通知成功"));
        if ("200".equals(statusCode)) {
            BigDecimal amount = body.getBigDecimal("amount");
            long v = amount.longValue() * 100;
            if (payOrder.getAmount() == v) {
                // 校验订单金额，明确订单支付状态为：支付成功
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
            } else {
                log.error("订单{}金额不一致！{}=={}", payOrder.getPayOrderId(), payOrder.getAmount(), v);
            }

        } else {
            if ("failed".equals(statusMsg)) {
                // 订单支付状态为：支付失败
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
            }
            channelRetMsg.setChannelErrMsg(body.getString("status_description"));
        }
        return channelRetMsg;
    }


    /**
     * 读取body内容
     *
     * @param request
     * @return
     */
    private String getBody(HttpServletRequest request) {
        StringBuffer data = new StringBuffer();
        String line = null;
        BufferedReader reader = null;
        try {
            reader = request.getReader();
            while (null != (line = reader.readLine())) {
                data.append(line);
            }
        } catch (IOException e) {
            ResponseEntity responseEntity = new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
            throw new ResponseException(responseEntity);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return data.toString();
    }

}
